home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / net_src.arc / ax25subr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-05-08  |  10.6 KB  |  471 lines

  1. #include <stdio.h>
  2. #include "global.h"
  3. #include "mbuf.h"
  4. #include "timer.h"
  5. #include "ax25.h"
  6. #include "lapb.h"
  7. #include "netuser.h"
  8. #include "ftp.h"
  9. #include "telnet.h"
  10. #include "iface.h"
  11. #include "finger.h"
  12. #include <ctype.h>
  13.  
  14. struct ax25_cb *ax25_cb[NHASH];
  15.  
  16. /* Default AX.25 parameters */
  17. int16 t1init = 10000 / MSPTICK;    /* FRACK of 10 seconds */
  18. int16 t2init = 1000 / MSPTICK;    /* 1 sec acknowledgment delay */
  19. int16 t3init = 0 / MSPTICK;    /* No keep-alive polling */
  20. int16 maxframe = 1;        /* Stop and wait */
  21. int16 n2 = 10;            /* 10 retries */
  22. int16 axwindow = 2048;        /* 2K incoming text before RNR'ing */
  23. int16 paclen = 256;        /* 256-byte I fields */
  24. int16 pthresh = 128;        /* Send polls for packets larger than this */
  25.  
  26. /* Address hash function. Exclusive-ORs each byte, ignoring
  27.  * such insignificant, annoying things as E and H bits
  28.  */
  29. static
  30. int16
  31. ax25hash(s)
  32. struct ax25_addr *s;
  33. {
  34.     register char x;
  35.     register int i;
  36.     register char *cp;
  37.  
  38.     x = 0;
  39.     cp = s->call;
  40.     for(i=ALEN; i!=0; i--)
  41.         x ^= *cp++ & 0xfe;
  42.     x ^= s->ssid & SSID;
  43.     return uchar(x) % NHASH;
  44. }
  45. /* Look up entry in hash table */
  46. struct ax25_cb *
  47. find_ax25(addr)
  48. register struct ax25_addr *addr;
  49. {
  50.     int16 hashval;
  51.     register struct ax25_cb *axp;
  52.     char i_state;
  53.  
  54.     /* Find appropriate hash chain */
  55.     hashval = ax25hash(addr);
  56.  
  57.     /* Search hash chain */
  58.     i_state = disable();
  59.     for(axp = ax25_cb[hashval]; axp != NULLAX25; axp = axp->next){
  60.         if(addreq(&axp->addr.dest,addr)){
  61.             restore(i_state);
  62.             return axp;
  63.         }
  64.     }
  65.     restore(i_state);
  66.     return NULLAX25;
  67. }
  68.  
  69. /* Remove address entry from hash table */
  70. del_ax25(axp)
  71. register struct ax25_cb *axp;
  72. {
  73.     int16 hashval;
  74.     char i_state;
  75.  
  76.     if(axp == NULLAX25)
  77.         return;
  78.     /* Remove from hash header list if first on chain */
  79.     hashval = ax25hash(&axp->addr.dest);
  80.     i_state = disable();
  81.  
  82.     /* Remove from chain list */
  83.     if(ax25_cb[hashval] == axp)
  84.         ax25_cb[hashval] = axp->next;
  85.     if(axp->prev != NULLAX25)
  86.         axp->prev->next = axp->next;
  87.     if(axp->next != NULLAX25)
  88.         axp->next->prev = axp->prev;
  89.  
  90.     /* Timers should already be stopped, but just in case... */
  91.     stop_timer(&axp->t1);
  92.     stop_timer(&axp->t2);
  93.     stop_timer(&axp->t3);
  94.  
  95.     /* Free allocated resources */
  96.     free_q(&axp->txq);
  97.     free_q(&axp->rxasm);
  98.     free_q(&axp->rxq);
  99.     free((char *)axp);
  100.  
  101.     restore(i_state);
  102. }
  103.  
  104. /* Create an ax25 control block. Allocate a new structure, if necessary,
  105.  * and fill it with all the defaults. The caller
  106.  * is still responsible for filling in the reply address
  107.  */
  108. struct ax25_cb *
  109. cr_ax25(addr)
  110. struct ax25_addr *addr;
  111. {
  112.     void recover(),send_ack(),pollthem(),ax_incom();
  113.     register struct ax25_cb *axp;
  114.     int16 hashval;
  115.     char i_state;
  116. #ifdef SID2
  117.     void mbx_state();
  118. #endif
  119.  
  120.     if(addr == NULLAXADDR)
  121.         return NULLAX25;
  122.  
  123.     if((axp = find_ax25(addr)) == NULLAX25){
  124.         /* Not already in table; create an entry
  125.          * and insert it at the head of the chain
  126.          */
  127.         /* Find appropriate hash chain */
  128.         hashval = ax25hash(addr);
  129.         i_state = disable();
  130.         axp = (struct ax25_cb *)calloc(1,sizeof(struct ax25_cb));
  131.         if(axp == NULLAX25)
  132.             return NULLAX25;
  133.         /* Insert at beginning of chain */
  134.         axp->prev = NULLAX25;
  135.         axp->next = ax25_cb[hashval];
  136.         if(axp->next != NULLAX25)
  137.             axp->next->prev = axp;
  138.         ax25_cb[hashval] = axp;
  139.         restore(i_state);
  140.     }
  141.     axp->maxframe = maxframe;
  142.     axp->window = axwindow;
  143.     axp->paclen = paclen;
  144.     axp->proto = V2;    /* Default, can be changed by other end */
  145.     axp->pthresh = pthresh;
  146.     axp->n2 = n2;
  147.     axp->t1.start = t1init;
  148.     axp->t1.func = recover;
  149.     axp->t1.arg = (char *)axp;
  150.  
  151.     axp->t2.start = t2init;
  152.     axp->t2.func = send_ack;
  153.     axp->t2.arg = (char *)axp;
  154.  
  155.     axp->t3.start = t3init;
  156.     axp->t3.func = pollthem;
  157.     axp->t3.arg = (char *)axp;
  158.  
  159. #ifdef SID2
  160.     axp->s_upcall = mbx_state;
  161. #endif
  162.     axp->r_upcall = ax_incom;
  163.     return axp;
  164. }
  165.  
  166. /*
  167.  * setcall - convert callsign plus substation ID of the form
  168.  * "KA9Q-0" to AX.25 (shifted) address format
  169.  *   Address extension bit is left clear
  170.  *   Return -1 on error, 0 if OK
  171.  */
  172. int
  173. setcall(out,call)
  174. struct ax25_addr *out;
  175. char *call;
  176. {
  177.     int csize;
  178.     unsigned ssid;
  179.     register int i;
  180.     register char *cp,*dp;
  181.     char c;
  182.  
  183.     if(out == (struct ax25_addr *)NULL || call == NULLCHAR || *call == '\0'){
  184.         return -1;
  185.     }
  186.     /* Find dash, if any, separating callsign from ssid
  187.      * Then compute length of callsign field and make sure
  188.      * it isn't excessive
  189.      */
  190.     dp = index(call,'-');
  191.     if(dp == NULLCHAR)
  192.         csize = strlen(call);
  193.     else
  194.         csize = dp - call;
  195.     if(csize > ALEN)
  196.         return -1;
  197.     /* Now find and convert ssid, if any */
  198.     if(dp != NULLCHAR){
  199.         dp++;    /* skip dash */
  200.         ssid = atoi(dp);
  201.         if(ssid > 15)
  202.             return -1;
  203.     } else
  204.         ssid = 0;
  205.     /* Copy upper-case callsign, left shifted one bit */
  206.     cp = out->call;
  207.     for(i=0;i<csize;i++){
  208.         c = *call++;
  209.         if(islower(c))
  210.             c = toupper(c);
  211.         *cp++ = c << 1;
  212.     }
  213.     /* Pad with shifted spaces if necessary */
  214.     for(;i<ALEN;i++)
  215.         *cp++ = ' ' << 1;
  216.     
  217.     /* Insert substation ID field and set reserved bits */
  218.     out->ssid = 0x60 | (ssid << 1);
  219.     return 0;
  220. }
  221. /* Set a digipeater string in an ARP table entry */
  222. setpath(out,in,cnt)
  223. char *out;    /* Target char array containing addresses in net form */
  224. char *in[];    /* Input array of tokenized callsigns in ASCII */
  225. int cnt;    /* Number of callsigns in array */
  226. {
  227.     struct ax25_addr addr;
  228.     char *putaxaddr();
  229.  
  230.     if(cnt == 0)
  231.         return;
  232.     while(cnt-- != 0){
  233.         setcall(&addr,*in++);
  234.         addr.ssid &= ~E;
  235.         out = putaxaddr(out,&addr);
  236.     }
  237.     out[-1] |= E;
  238. }
  239. addreq(a,b)
  240. register struct ax25_addr *a,*b;
  241. {
  242.     if(memcmp(a->call,b->call,ALEN) != 0)
  243.         return 0;
  244.     if((a->ssid & SSID) != (b->ssid & SSID))
  245.         return 0;
  246.     return 1;
  247. }
  248. /* Convert encoded AX.25 address to printable string */
  249. pax25(e,addr)
  250. char *e;
  251. struct ax25_addr *addr;
  252. {
  253.     register int i;
  254.     char c,*cp;
  255.  
  256.     cp = addr->call;
  257.     for(i=ALEN;i != 0;i--){
  258.         c = (*cp++ >> 1) & 0x7f;
  259.         if(c == ' ')
  260.             break;
  261.         *e++ = c;
  262.     }
  263.     if ((addr->ssid & SSID) != 0)
  264.         sprintf(e,"-%d",(addr->ssid >> 1) & 0xf);    /* ssid */
  265.     else
  266.         *e = 0;
  267. }
  268. /* Print a string of AX.25 addresses in the form
  269.  * "KA9Q-0 [via N4HY-0,N2DSY-2]"
  270.  * Designed for use by ARP - arg is a char string
  271.  */
  272. psax25(e,addr)
  273. register char *e;
  274. register char *addr;
  275. {
  276.     int i;
  277.     struct ax25_addr axaddr;
  278.     char tmp[16];
  279.     char *getaxaddr();
  280.  
  281.     e[0] = '\0';    /* Give strcat a staritng point */
  282.     for(i=0;;i++){
  283.         /* Create local copy in host-format structure */
  284.         addr = getaxaddr(&axaddr,addr);
  285.  
  286.         /* Create ASCII representation and append to output */
  287.         pax25(tmp,&axaddr);
  288.         strcat(e,tmp);
  289.  
  290.         if(axaddr.ssid & E)
  291.             break;
  292.         if(i == 0)
  293.             strcat(e," via ");
  294.         else
  295.             strcat(e,",");
  296.         /* Not really necessary, but speeds up subsequent strcats */
  297.         e += strlen(e);
  298.     }
  299. }
  300. char *
  301. getaxaddr(ap,cp)
  302. register struct ax25_addr *ap;
  303. register char *cp;
  304. {
  305.     memcpy(ap->call,cp,ALEN);
  306.     cp += ALEN;
  307.     ap->ssid = *cp++;
  308.     return cp;
  309. }
  310. char *
  311. putaxaddr(cp,ap)
  312. register char *cp;
  313. register struct ax25_addr *ap;
  314. {
  315.     memcpy(cp,ap->call,ALEN);
  316.     cp += ALEN;
  317.     *cp++ = ap->ssid;
  318.     return cp;
  319. }
  320.  
  321. /* Convert a host-format AX.25 header into a mbuf ready for transmission */
  322. struct mbuf *
  323. htonax25(hdr,data)
  324. register struct ax25 *hdr;
  325. struct mbuf *data;
  326. {
  327.     struct mbuf *bp;
  328.     register char *cp;
  329.     register int16 i;
  330.  
  331.     if(hdr == (struct ax25 *)NULL || hdr->ndigis > MAXDIGIS)
  332.         return NULLBUF;
  333.  
  334.     /* Allocate space for return buffer */
  335.     i = AXALEN * (2 + hdr->ndigis);
  336.     if((bp = pushdown(data,i)) == NULLBUF)
  337.         return NULLBUF;
  338.  
  339.     /* Now convert */
  340.     cp = bp->data;
  341.  
  342.     hdr->dest.ssid &= ~E;    /* Dest E-bit is always off */
  343.     /* Encode command/response in C bits */
  344.     switch(hdr->cmdrsp){
  345.     case COMMAND:
  346.         hdr->dest.ssid |= C;
  347.         hdr->source.ssid &= ~C;
  348.         break;
  349.     case RESPONSE:
  350.         hdr->dest.ssid &= ~C;
  351.         hdr->source.ssid |= C;
  352.         break;
  353.     default:
  354.         hdr->dest.ssid &= ~C;
  355.         hdr->source.ssid &= ~C;
  356.         break;
  357.     }
  358.     cp = putaxaddr(cp,&hdr->dest);
  359.  
  360.     /* Set E bit on source address if no digis */
  361.     if(hdr->ndigis == 0){
  362.         hdr->source.ssid |= E;
  363.         putaxaddr(cp,&hdr->source);
  364.         return bp;
  365.     }
  366.     hdr->source.ssid &= ~E;
  367.     cp = putaxaddr(cp,&hdr->source);
  368.  
  369.     /* All but last digi get copied with E bit off */
  370.     for(i=0; i < hdr->ndigis - 1; i++){
  371.         hdr->digis[i].ssid &= ~E;
  372.         cp = putaxaddr(cp,&hdr->digis[i]);
  373.     }
  374.     hdr->digis[i].ssid |= E;
  375.     cp = putaxaddr(cp,&hdr->digis[i]);
  376.     return bp;
  377. }
  378. /* Convert an AX.25 ARP table entry into a host format address structure
  379.  * ready for use in transmitting a packet
  380.  */
  381. int
  382. atohax25(hdr,hwaddr,source)
  383. register struct ax25 *hdr;
  384. register char *hwaddr;
  385. struct ax25_addr *source;
  386. {
  387.     extern struct ax25_addr mycall;
  388.     register struct ax25_addr *axp;
  389.  
  390.     hwaddr = getaxaddr(&hdr->dest,hwaddr);    /* Destination address */
  391.     ASSIGN(hdr->source,*source);        /* Source address */
  392.     if(hdr->dest.ssid & E){
  393.         /* No digipeaters */
  394.         hdr->ndigis = 0;
  395.         hdr->dest.ssid &= ~E;
  396.         hdr->source.ssid |= E;
  397.         return 2;
  398.     }
  399.     hdr->source.ssid &= ~E;
  400.     hdr->dest.ssid &= ~E;
  401.     for(axp = hdr->digis; axp < &hdr->digis[MAXDIGIS]; axp++){
  402.         hwaddr = getaxaddr(axp,hwaddr);
  403.         if(axp->ssid & E){
  404.             hdr->ndigis = axp - hdr->digis + 1;
  405.             return hdr->ndigis;
  406.         }
  407.     }
  408.     return -1;
  409. }
  410. /* Convert a network-format AX.25 header into a host format structure
  411.  * Return -1 if error, number of addresses if OK
  412.  */
  413. int
  414. ntohax25(hdr,bpp)
  415. register struct ax25 *hdr;    /* Output structure */
  416. struct mbuf **bpp;
  417. {
  418.     register struct ax25_addr *axp;
  419.     char *getaxaddr();
  420.     char buf[AXALEN];
  421.  
  422.     if(pullup(bpp,buf,AXALEN) < AXALEN)
  423.         return -1;
  424.     getaxaddr(&hdr->dest,buf);
  425.  
  426.     if(pullup(bpp,buf,AXALEN) < AXALEN)
  427.         return -1;
  428.     getaxaddr(&hdr->source,buf);
  429.  
  430.     /* Process C bits to get command/response indication */
  431.     if((hdr->source.ssid & C) == (hdr->dest.ssid & C))
  432.         hdr->cmdrsp = UNKNOWN;
  433.     else if(hdr->source.ssid & C)
  434.         hdr->cmdrsp = RESPONSE;
  435.     else
  436.         hdr->cmdrsp = COMMAND;
  437.  
  438.     hdr->ndigis = 0;
  439.     if(hdr->source.ssid & E)
  440.         return 2;    /* No digis */
  441.  
  442.     /* Process digipeaters */
  443.     for(axp = hdr->digis;axp < &hdr->digis[MAXDIGIS]; axp++){
  444.         if(pullup(bpp,buf,AXALEN) < AXALEN)
  445.             return -1;
  446.         getaxaddr(axp,buf);
  447.         if(axp->ssid & E){    /* Last one */
  448.             hdr->ndigis = axp - hdr->digis + 1;
  449.             return hdr->ndigis + 2;            
  450.         }
  451.     }
  452.     return -1;    /* Too many digis */
  453. }
  454.  
  455. /* Figure out the frame type from the control field
  456.  * This is done by masking out any sequence numbers and the
  457.  * poll/final bit after determining the general class (I/S/U) of the frame
  458.  */
  459. int16
  460. ftype(control)
  461. register char control;
  462. {
  463.     if((control & 1) == 0)    /* An I-frame is an I-frame... */
  464.         return I;
  465.     if(control & 2)        /* U-frames use all except P/F bit for type */
  466.         return(control & ~PF);
  467.     else            /* S-frames use low order 4 bits for type */
  468.         return(control & 0xf);
  469. }
  470.  
  471.